package cn.flying.cloud.message.core.service;

import javax.annotation.Resource;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.springframework.util.Assert;

import cn.flying.cloud.base.common.utils.Ft;
import cn.flying.cloud.base.mail.template.VelocityEngineTemplate;
import cn.flying.cloud.message.bo.MsgStorageBo;
import cn.flying.cloud.message.bo.MsgTemplateBo;
import cn.flying.cloud.message.core.enums.SendType;
import cn.flying.cloud.message.core.factory.MessageSenderStrategyFactory;
import cn.flying.cloud.message.core.sender.disruptor.AsyncMessageSender;
import cn.flying.cloud.message.core.strategy.MessageSenderStrategy;
import cn.flying.cloud.message.entity.MsgInfo;
import cn.flying.cloud.message.model.MessageRequest;
import cn.flying.cloud.message.service.MsgInfoService;
import cn.flying.cloud.message.service.MsgStorageService;
import cn.flying.cloud.message.service.MsgTemplateService;
import cn.flying.cloud.system.dict.service.DictDataService;

/**
 * 消息发送抽象类
 *
 * @author: admin
 * @date: 2025年03月27日 16:13
 * @version: 1.0
 */
public abstract class AbstractMessageSenderService {

    @Resource
    private MsgStorageService msgStorageService;
    @Resource
    private MsgTemplateService msgTemplateService;
    @Resource
    private VelocityEngineTemplate engineTemplate;
    @Resource
    private MsgInfoService msgInfoService;
    @Resource
    private MessageSenderStrategyFactory messageSenderStrategyFactory;
    @Resource
    private AsyncMessageSender messageSender;
    @Resource
    private DictDataService dictDataService;

    public void send(MessageRequest request, SendType sendType, boolean html) {
        // 1、根据租户ID查询当前租户默认的消息存储配置
        MsgStorageBo storage = findMsgStorage(request.getTenantId(), sendType);
        // 2、判断是否需要做模板填充，如需要调用模板转换方法生成真正的消息内容
        if (Ft.String.isNotBlank(request.getTplId())) {
            setMsgContent(request);
        }
        // 3、根据厂商获取发送策略
        MessageSenderStrategy messageSenderStrategy;
        if (SendType.EMAIL.name().equals(sendType.name())) {
            messageSenderStrategy = messageSenderStrategyFactory.getMessageSender("email");
        } else {
            messageSenderStrategy = messageSenderStrategyFactory.getMessageSender(storage.getVendorCode());
        }

        // 4、保存消息下发记录
        saveMsgInfo(request, sendType, storage);

        // 5、异步发送
        messageSender.publish(request, storage, messageSenderStrategy, sendType, html);
    }

    private MsgStorageBo findMsgStorage(String tenantId, SendType sendType) {
        MsgStorageBo param = new MsgStorageBo();
        param.setMsgType(sendType.name());
        param.setTenantId(tenantId);
        param.setStatus("Y");
        param.setIsDefault("Y");
        MsgStorageBo storage = msgStorageService.getOneObj(param);
        Assert.notNull(storage, "当前租户配置不存在！");
        return storage;
    }

    private void setMsgContent(MessageRequest request) {
        MsgTemplateBo template = new MsgTemplateBo();
        template.setTplId(request.getTplId());
        template = msgTemplateService.getOneObj(template);
        Assert.notNull(template, "消息模板不存在！");
        String content = engineTemplate.process(request.getParam(), template.getTplId(), template.getContent());
        request.setContent(content);
    }

    private void saveMsgInfo(MessageRequest request, SendType sendType, MsgStorageBo storage) {
        List<MsgInfo> infos = new ArrayList<>();
        Map<String, String> serviceNames = dictDataService.getDict("service_name");
        for (String recipient : request.getRecipients()) {
            MsgInfo info = new MsgInfo();
            info.setRequestNo(request.getRequestNo());
            info.setServiceName(serviceNames.get(request.getServiceCode()));
            info.setServiceCode(request.getServiceCode());
            info.setTitle(request.getTitle());
            info.setAccount(recipient);
            info.setContent(request.getContent());
            info.setPushStatus("S");
//            info.setSendStatus("");
            info.setMode(sendType.name());
            info.setType(sendType.name());
            info.setVendorCode(storage.getVendorCode());
            info.setVendorName(storage.getVendorName());
            info.setTenantId(request.getTenantId());

            infos.add(info);
        }

        msgInfoService.saveBatch(infos);
    }

}    